﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{

    public delegate void EventHandle(string e,params object[] args);
    public delegate void EventEnumHandle(Enum e,params object[] args);
    /// <summary>
    /// 全局事件管理器
    /// </summary>
    public class EventManager
    {
        public static void Clear()
        {
            RemoveAllEvent();
            RemoveAllEnumEvent();
        }

        #region 以string为Key的事件派发

        private static Dictionary<string, EventHandle> mEventStringDic = new Dictionary<string, EventHandle>();
        private static Dictionary<string, List<EventHandle>> mUseOnceEventStringDic = new Dictionary<string, List<EventHandle>>();


        /// <summary>
        /// 添加监听事件
        /// </summary>
        /// <param name="isUseOnce">注册为一次事件</param>
        public static void AddEvent(string eventKey,EventHandle handle,bool isUseOnce = false)
        {
            if (isUseOnce)
            {
                if (mUseOnceEventStringDic.ContainsKey(eventKey))
                {
                    if (!mUseOnceEventStringDic[eventKey].Contains(handle))
                    {
                        mUseOnceEventStringDic[eventKey].Add(handle);
                    }
                    else
                    {
                        Debug.LogWarning("already existing EventType: " + eventKey + " handle: " + handle);
                    }
                }
                else
                {
                    List<EventHandle> temp = new List<EventHandle>();
                    temp.Add(handle);
                    mUseOnceEventStringDic.Add(eventKey, temp);
                }
            }
            else
            {
                if (mEventStringDic.ContainsKey(eventKey))
                {
                    mEventStringDic[eventKey] += handle;
                }
                else
                {
                    mEventStringDic.Add(eventKey, handle);
                }
            }
        }

        /// <summary>
        /// 移除某类事件的一个回调
        /// </summary>
        /// <param name="type"></param>
        /// <param name="handle"></param>
        public static void RemoveEvent(string type, EventHandle handle)
        {
            if (mUseOnceEventStringDic.ContainsKey(type))
            {
                if (mUseOnceEventStringDic[type].Contains(handle))
                {
                    mUseOnceEventStringDic[type].Remove(handle);
                    if (mUseOnceEventStringDic[type].Count == 0)
                    {
                        mUseOnceEventStringDic.Remove(type);
                    }
                }
            }

            if (mEventStringDic.ContainsKey(type))
            {
                mEventStringDic[type] -= handle;
            }
        }

        /// <summary>
        /// 移除某类事件
        /// </summary>
        /// <param name="type"></param>
        public static void RemoveEvent(string type)
        {
            if (mUseOnceEventStringDic.ContainsKey(type))
            {
                mUseOnceEventStringDic.Remove(type);
            }

            if (mEventStringDic.ContainsKey(type))
            {
                mEventStringDic.Remove(type);
            }
        }

        /// <summary>
        /// 移除所有事件
        /// </summary>
        public static void RemoveAllEvent()
        {
            mUseOnceEventStringDic.Clear();

            mEventStringDic.Clear();
        }

        public static void DispatchEvent(string type,params object[] args)
        {
            if (mEventStringDic.ContainsKey(type))
            {
                try
                {
                    if (mEventStringDic[type] != null)
                    {
                        mEventStringDic[type](type,args);
                    }

                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }

            if (mUseOnceEventStringDic.ContainsKey(type))
            {
                for (int i = 0; i < mUseOnceEventStringDic[type].Count; i++)
                {
                    //遍历委托链表
                    foreach (EventHandle callBack in mUseOnceEventStringDic[type][i].GetInvocationList())
                    {
                        try
                        {
                            callBack(type, args);
                        }
                        catch (Exception e)
                        {
                            Debug.LogError(e.ToString());
                        }
                    }
                }
                //事件触发一次，则清除
                RemoveEvent(type);
            }
        }

        #endregion

        #region 以Enum为Key的事件派发

        private static Dictionary<Enum, EventEnumHandle> mEventDic = new Dictionary<Enum, EventEnumHandle>();
        private static Dictionary<Enum, List<EventEnumHandle>> mUseOnceEventDic = new Dictionary<Enum, List<EventEnumHandle>>();

        /// <summary>
        /// 添加事件及回调
        /// </summary>
        /// <param name="type">事件枚举</param>
        /// <param name="handle">回调</param>
        /// <param name="isUseOnce"></param>
        public static void AddEvent(Enum type, EventEnumHandle handle, bool isUseOnce = false)
        {
            if (isUseOnce)
            {
                if (mUseOnceEventDic.ContainsKey(type))
                {
                    if (!mUseOnceEventDic[type].Contains(handle))
                        mUseOnceEventDic[type].Add(handle);
                    else
                        Debug.LogWarning("already existing EventType: " + type + " handle: " + handle);
                }
                else
                {
                    List<EventEnumHandle> temp = new List<EventEnumHandle>();
                    temp.Add(handle);
                    mUseOnceEventDic.Add(type, temp);
                }
            }
            else
            {
                if (mEventDic.ContainsKey(type))
                {
                    mEventDic[type] += handle;
                }
                else
                {
                    mEventDic.Add(type, handle);
                }
            }
        }

        /// <summary>
        /// 移除某类事件的一个回调
        /// </summary>
        /// <param name="type"></param>
        /// <param name="handle"></param>
        public static void RemoveEvent(Enum type, EventEnumHandle handle)
        {
            if (mUseOnceEventDic.ContainsKey(type))
            {
                if (mUseOnceEventDic[type].Contains(handle))
                {
                    mUseOnceEventDic[type].Remove(handle);
                    if (mUseOnceEventDic[type].Count == 0)
                    {
                        mUseOnceEventDic.Remove(type);
                    }
                }
            }

            if (mEventDic.ContainsKey(type))
            {
                mEventDic[type] -= handle;
                if (mEventDic[type] == null)
                    mEventDic.Remove(type);
            }
        }

        /// <summary>
        /// 移除某类事件
        /// </summary>
        /// <param name="type"></param>
        public static void RemoveEvent(Enum type)
        {
            if (mUseOnceEventDic.ContainsKey(type))
            {
                mUseOnceEventDic.Remove(type);
            }

            if (mEventDic.ContainsKey(type))
            {
                mEventDic.Remove(type);
            }
        }

        public static void RemoveAllEnumEvent()
        {
            mUseOnceEventDic.Clear();
            mEventDic.Clear();
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="type"></param>
        /// <param name="args"></param>
        public static void DispatchEvent(Enum type, params object[] args)
        {
            if (mEventDic.ContainsKey(type))
            {
                try
                {
                    if (mEventDic[type] != null)
                    {
                        mEventDic[type](type,args);
                    }
                    else
                    {
                        mEventDic.Remove(type);
                    }

                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }

            if (mUseOnceEventDic.ContainsKey(type))
            {
                for (int i = 0; i < mUseOnceEventDic[type].Count; i++)
                {
                    //遍历委托链表
                    foreach (var p in mUseOnceEventDic[type])
                    {
                        try
                        {
                            p?.Invoke(type, args);
                        }
                        catch (Exception e)
                        {
                            Debug.LogError(e.ToString());
                        }
                    }
                }
                RemoveEvent(type);
            }
        }

        #endregion

    }

}

